from manim import *
'''
    乘法的算式由被乘数、乘数，中间加一个乘号组成
    可以使用x轴来表示被乘数，使用y轴来表示乘数，画出两条线段
    乘法的计算过程，可以理解为先在x轴上画出被乘数个正方形，这代表被乘数乘以1的结果
    然后在y轴方向上，重复画这组正方形，算上之前的第一组正方形，一共要画乘数次
    最后正方形的总数量，也就是乘法计算的结果了
    其实也就是以被乘数和乘数分别作为宽和高的矩形的面积啦
    
'''

class MultiplicationVisualization(Scene):
    def construct(self):
        # 设置行数和列数
        rows = 3
        cols = 4
        
        # 创建自定义 LaTeX 模板
        tex_template = TexTemplate()
        tex_template.add_to_preamble(r"\usepackage{ctex}")

        # 设置坐标轴的长度，使得 x 和 y 的单位长度一致，并且增加一些额外的空间
        unit_length = 1
        axes = Axes(
            x_range=[0, cols + 2, 1],
            y_range=[0, rows + 2, 1],
            x_length=(cols + 2) * unit_length,
            y_length=(rows + 2) * unit_length,
            axis_config={"include_numbers": True},
        ).add_coordinates()

        # 创建 x 轴上的线段（代表被乘数）
        x_line = Line(
            start=axes.c2p(0, 0),
            end=axes.c2p(cols, 0),
            color=BLUE
        )
        
        # 创建 y 轴上的线段（代表乘数）
        y_line = Line(
            start=axes.c2p(0, 0),
            end=axes.c2p(0, rows),
            color=RED
        )

        # 创建行和列的标签
        x_label = Tex(f"被乘数: {cols}", color=BLUE, tex_template=tex_template).next_to(axes, DOWN).scale(0.7)
        y_label = Tex(f"乘数: {rows}", color=RED, tex_template=tex_template).next_to(axes, LEFT).scale(0.7)
        
        # 创建乘法表达式（不显示结果）
        multiplication_expression = Tex(f"${cols} \\times {rows}$", color=WHITE)
        multiplication_expression.to_edge(UP)

        # 创建乘法结果表达式
        result_expression = Tex(f"${cols} \\times {rows} = {rows * cols}$", color=WHITE)
        result_expression.next_to(multiplication_expression, DOWN)

        # 显示乘法表达式（不显示结果）
        self.play(Write(multiplication_expression))
        
        # 显示坐标轴
        self.play(Create(axes))
        
        # 显示 x 轴上的线段（被乘数）
        self.play(Create(x_line))
        self.play(Write(x_label))
        
        # 显示 y 轴上的线段（乘数）
        self.play(Create(y_line))
        self.play(Write(y_label))
        
        # 创建乘法结果的正方形矩阵
        matrix_squares = VGroup()
        for i in range(rows):
            for j in range(cols):
                square = Square(side_length=unit_length)
                square.set_fill(GREEN if i > 0 else YELLOW, opacity=0.5)  # 第一行用黄色，其它行用绿色
                square.set_stroke(GREEN_E, width=2)
                square.move_to(axes.c2p(j + 0.5, i + 0.5))
                matrix_squares.add(square)

        # 显示第一行的正方形
        self.play(LaggedStart(*[Create(matrix_squares[i]) for i in range(cols)], lag_ratio=0.1))
        
        # 更换颜色，强调被乘数的乘法运算
        self.play(*[square.animate.set_fill(GREEN, opacity=0.5) for square in matrix_squares[:cols]])

        # 添加文字说明
        explanation_text = Tex(f"接下来要把被乘数 {cols} 进行 {rows} 次加法运算", color=WHITE, tex_template=tex_template).scale(0.7)
        explanation_text.to_edge(DOWN)
        # x_label淡出，y_label淡出
        self.play(FadeOut(x_label),FadeOut(y_label))
        self.play(Write(explanation_text))
        
        # 显示剩下的正方形
        self.play(LaggedStart(*[Create(matrix_squares[i]) for i in range(cols, len(matrix_squares))], lag_ratio=0.1))
        
        # 显示乘法结果表达式
        self.play(Transform(multiplication_expression, result_expression))
        
        # 保持动画一段时间
        self.wait(2)

# 运行代码
# 保存修改后的 Python 文件（例如 MultiplicationVisualization.py），然后在命令行中运行以下命令：
# manim -pql .\MultiplicationVisualization.py MultiplicationVisualization